package dao

import (
	"context"
	"errors"
	"go.uber.org/zap"
	"gorm.io/gorm"
	"seichat/biz"
	"seichat/common"
	"seichat/models"
	"strconv"
	"time"
)

type UserDao interface {
	GetUserList(ctx context.Context) ([]*models.User, error)
	FindUserByNameAndPwd(ctx context.Context, name string, password string) (*models.User, error)
	FindUserByName(ctx context.Context, name string) (*models.User, error)
	FindUserIsExist(ctx context.Context, name string) (*models.User, error)
	FindUserId(ctx context.Context, Id uint) (*models.User, error)
	FindUserByPhone(ctx context.Context, phone string) (*models.User, error)
	FindUerByEmail(ctx context.Context, email string) (*models.User, error)
	UpdateUser(ctx context.Context, user models.User) (*models.User, error)
	DeleteUser(ctx context.Context, user models.User) error
	CreateUser(ctx context.Context, user models.User) (*models.User, error)
}
type GormUserDao struct {
	DB *gorm.DB
}

func NewUserDao(db *gorm.DB) *GormUserDao {
	return &GormUserDao{DB: db}
}

// GetUserList 获取用户列表
func (u *GormUserDao) GetUserList(ctx context.Context) ([]*models.User, error) {
	var list []*models.User
	tx := u.DB.WithContext(ctx).Find(&list)
	if err := EnsureRecordFound(tx); err != nil {
		return nil, err
	}
	return list, nil
}

// FindUserByNameAndPwd 昵称和密码查询
func (u *GormUserDao) FindUserByNameAndPwd(ctx context.Context, name string, password string) (*models.User, error) {
	user := models.User{}
	tx := u.DB.WithContext(ctx).Where("name = ? and pass_word=?", name, password).First(&user)
	if tx.RowsAffected == 0 || handleGormError(tx) != nil {
		return nil, biz.RecordNotFound
	}
	//登录识别
	t := strconv.Itoa(int(time.Now().Unix()))
	//md5 解
	temp := common.Md5encoder(t)
	tx = u.DB.WithContext(ctx).Model(&user).Where("id = ?", user.ID).Update("identity", temp)
	if tx.RowsAffected == 0 || handleGormError(tx) != nil {
		return nil, errors.New("写入identity失败")
	}
	return &user, nil
}

// FindUserByName  根据用户名查询用户
func (u *GormUserDao) FindUserByName(ctx context.Context, name string) (*models.User, error) {
	user := models.User{}
	tx := u.DB.WithContext(ctx).Where("name = ?", name).First(&user)
	if err := EnsureRecordFound(tx); err != nil {
		return nil, err
	}
	return &user, nil
}

// FindUserIsExist 检查用户是否存在 注册用
func (u *GormUserDao) FindUserIsExist(ctx context.Context, name string) (*models.User, error) {
	user := models.User{}
	tx := u.DB.WithContext(ctx).Where("name = ?", name).First(&user)
	if err := EnsureRecordFound(tx); err != nil {
		return nil, err
	}
	return &user, nil
}

// FindUserId 根据 id 查询用户
func (u *GormUserDao) FindUserId(ctx context.Context, Id uint) (*models.User, error) {
	user := models.User{}
	tx := u.DB.WithContext(ctx).Where(Id).First(&user)
	if err := EnsureRecordFound(tx); err != nil {
		return nil, err
	}
	return &user, nil
}

// FindUserByPhone 根据电话查询用户
func (u *GormUserDao) FindUserByPhone(ctx context.Context, phone string) (*models.User, error) {
	user := models.User{}
	tx := u.DB.WithContext(ctx).Where("phone = ?", phone).First(&user)
	if err := EnsureRecordFound(tx); err != nil {
		return nil, err
	}
	return &user, nil
}

// FindUerByEmail 根据邮件查询用户
func (u *GormUserDao) FindUerByEmail(ctx context.Context, email string) (*models.User, error) {
	user := models.User{}
	tx := u.DB.WithContext(ctx).Where("email = ?", email).First(&user)
	if err := EnsureRecordFound(tx); err != nil {
		return nil, err
	}
	return &user, nil
}

// UpdateUser 更新用户
func (u *GormUserDao) UpdateUser(ctx context.Context, user models.User) (*models.User, error) {
	tx := u.DB.WithContext(ctx).Model(&user).Updates(models.User{
		Name:     user.Name,
		PassWord: user.PassWord,
		Gender:   user.Gender,
		Phone:    user.Phone,
		Email:    user.Email,
		Avatar:   user.Avatar,
		Salt:     user.Salt,
	})
	if err := EnsureRecordFound(tx); err != nil {
		return nil, err
	}
	return &user, nil
}

// DeleteUser 删除用户
func (u *GormUserDao) DeleteUser(ctx context.Context, user models.User) error {
	tx := u.DB.WithContext(ctx).Delete(&user)
	return EnsureRecordDeleted(tx)
}

// CreateUser 新建用户
func (u *GormUserDao) CreateUser(ctx context.Context, user models.User) (*models.User, error) {
	tx := u.DB.WithContext(ctx).Create(&user)
	if tx.RowsAffected == 0 {
		zap.S().Info("新建用户失败")
		return nil, errors.New("新增用户失败")
	}
	return &user, nil
}
